package com.langyiquan.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.internal.org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.langyiquan.bo.UserInfoBO;
import com.langyiquan.bo.WechatLoginBO;
import com.langyiquan.doo.WechatRawDataDO;
import com.langyiquan.mapper.UsersMapper;
import com.langyiquan.pojo.Users;
import com.langyiquan.service.UserService;
import com.langyiquan.service.WechatService;
import com.langyiquan.utils.HttpUtils;
import com.langyiquan.utils.RedisOperator;
import jodd.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class WechatServiceImpl implements WechatService {

    private static final String REQUEST_URL = "https://api.weixin.qq.com/sns/jscode2session";
    private static final String code  = "authorization_code";

    final static Logger logger = LoggerFactory.getLogger(WechatServiceImpl.class);

    @Autowired
    private RedisOperator redisOperator;

    @Autowired
    private UserService userService;

    @Override
    public Users getUserInfo(WechatLoginBO wechatLoginBO) {
        Map<String, Object> userInfoMap = new HashMap<>();
        JSONObject sessionKeyOpenId = null;
        try {
            sessionKeyOpenId = getSessionKeyOrOpenId(wechatLoginBO.getCode());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 获取openId && sessionKey
        String openId = sessionKeyOpenId.getString("openid");
        String sessionKey = sessionKeyOpenId.getString("session_key");
        System.out.println("session_key:"+sessionKey);
        redisOperator.set("session_key",sessionKey,7000);

        Users insertOrUpdateUser = buildWechatUserAuthInfoDO(wechatLoginBO, sessionKey, openId);

        // 根据openid查询用户，这里的查询service自己写，就不贴出来了
        Users user = userService.getUserByOpenId(openId);
        if (user == null) {
            user = userService.createWechatUser(insertOrUpdateUser);
        } else {
            user = userService.updateWechatUserByOpenId(user.getId(),insertOrUpdateUser);
        }

        return user;
    }

    private JSONObject getSessionKeyOrOpenId(String code) throws Exception {
        Map<String, String> requestUrlParam = new HashMap<>();
        // 小程序appId，自己补充
        requestUrlParam.put("appid", "wx2f9338a8bc87bdd6");

        // 小程序secret，自己补充
        requestUrlParam.put("secret", "261716a22b733fa0e129b375648347ed");
        // 小程序端返回的code
        requestUrlParam.put("js_code", code);
        // 默认参数
        requestUrlParam.put("grant_type", "authorization_code");

        // 发送post请求读取调用微信接口获取openid用户唯一标识
        String result = HttpUtils.doPost(REQUEST_URL, requestUrlParam);
        return JSON.parseObject(result);
    }

    private Users buildWechatUserAuthInfoDO(WechatLoginBO wechatLoginBO, String sessionKey, String openId){
        Users users = new Users();
        users.setOpenid(openId);
        System.out.println(wechatLoginBO.getEncryptedData());
        JSONObject encryptedData = getUserInfo(wechatLoginBO.getEncryptedData(), sessionKey, wechatLoginBO.getIv());
        System.out.println("encryptedData:"+encryptedData);
//            if (encryptedData != null){
//                users.setUnionid(encryptedData.getString("unionId"));
//                users.setNickname(encryptedData.getString("nickName"));
//                users.setFace(encryptedData.getString("avatarUrl"));
//                users.setSex(encryptedData.getInteger("gender"));
//            }

        return users;
    }


    public static JSONObject getUserInfo(String encryptedData,String sessionKey,String iv){
        // 被加密的数据
        byte[] dataByte = Base64.decode(encryptedData);
        // 加密秘钥
        byte[] keyByte = Base64.decode(sessionKey);
        // 偏移量
        byte[] ivByte = Base64.decode(iv);
        try {
            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init( Cipher.DECRYPT_MODE, spec, parameters);// 初始化
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, "UTF-8");
                return JSON.parseObject(result);
            }
        } catch (Exception e) {
            System.out.println("error:"+e.getMessage());
        }
        return null;
    }


}
